<?php


namespace app\admin\controller;


use app\admin\library\PHPFileSystem;
use app\admin\model\FileType;
use app\BaseController;

use think\facade\Session;
use think\facade\View;
use think\helper\Str;
use think\Request;

class File extends BaseController
{
    protected $childrenAdminIds = [];

    public function initialize()
    {
        parent::initialize();
        $this->childrenAdminIds = $this->auth->getChildrenAdminIds(true);
    }

    //显示
    public function index(Request $request)
    {
        if ($request->isAjax()) {
            $arr[] = [
                'id' => 1,
                'pid' => 0,
                'value' => "初始化文件夹",
                'open' => true,
                'type' => "folder",
                'size' => "0",
                'date' => time()
            ];
            $file = \app\admin\model\File::where('admin_id', 'in', $this->childrenAdminIds)->select();

            if (!empty($file)) {
                $i = 1;
                foreach ($file as $k => $value) {
                    $arr[]['id'] = $value['id'];
                    $arr[$i]['pid'] = $value['pid'];
                    $arr[$i]['value'] = $value['name'];
                    $arr[$i]['open'] = true;
                    $arr[$i]['size'] =  $value['size'];
                    $arr[$i]['type'] = $value['suffix'];
                    $arr[$i]['date'] = strtotime($value['create_time']);
                    $i++;
                }
            }
            $list = toChildrenPid($arr, 'data');
            return json($list);
        }
        return View::fetch();
    }

    /**
     * [action description]
     * @param  Request $request [description]
     * @return [type]           [description]
     * 公共方法
     */
    public function action(Request $request)
    {
        $action = $request->param('action');
        $source = $request->param('source');
        $target = $request->param('target');
        $admin_id = $this->auth->id;
        $file_copy = \app\admin\model\File::where('admin_id', 'in', $this->childrenAdminIds)->select();
        if ($action == "create") {
            $data['name'] = $source;
            $data['create_id'] = $request->param('id');
            $data['pid'] = $target;
            $data['suffix'] = "folder";
            $data['file_type'] = "folder";
            $data['admin_id'] = $admin_id;
            \app\admin\model\File::create($data);
        } else if ($action == "rename") {
            $file = \app\admin\model\File::find((int)$source);
            $file->name = $target;
            $file->save();
            //\app\admin\model\File::update(['name' => $target, 'id' => );
        } else if ($action == "remove") {
            $ids = explode(',', $source);
            \app\admin\model\File::destroy($ids);
        } else if ($action == "move") {
            $data['id'] = $source;
            $data['pid'] = $target;
            \app\admin\model\File::update($data);
        } else if ($action == "copy") { //文件
            $file = \app\admin\model\File::find($source);
            $file_ids = getChildsId($file_copy, $source);
            array_push($file_ids, $source);
            if (!empty($file_ids)) {
                $data = \app\admin\model\File::where('id', 'in', $file_ids)->select()->toArray();
                $source_data = get_attrss($data, $file->pid);
                $this->add($source_data, $target);
            }
        } else if ($action == "upload") {
            $file = request()->file('upload');
            $savename = \think\facade\Filesystem::disk('public')->putFile('topic', $file, 'uniqid');
            $abc = pathinfo($savename);
//            dd(mime_content_type('storage/' . $savename));
            $data['pid'] = $target;
            $data['name'] = $request->param('upload_fullpath');
            $data['path'] = $savename;
            $data['size'] = filesize('storage/' . $savename);
            $data['suffix'] = $abc['extension'];
            $data['admin_id'] = $admin_id;
            $data['file_type'] = "file";
            \app\admin\model\File::create($data);
        } else if ($action == "download") {
            $this->FileDownload($source);
        }
    }

    //递归新增
    public function add($data, $target)
    {
        foreach ($data as $key => $v) {
            $data_id = \app\admin\model\File::create([
                'name' => $v['name'],
                'pid' => $target,
                'path' => $v['suffix'],
                'admin_id' => $this->auth->id,
                'file_type' => $v['file_type'],
                'size' => $v['size'],
                'suffix' => $v['size'],
            ]);
            if (isset($v['children'])) {
                $this->add($v['children'], $data_id->id);
            }
        }
    }

    //切片上传
    public function cut_upload()
    {
        $tmp_dir = 'uploads/file';
        header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
        header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
        header("Content-type: text/html; charset=gbk32");
        header("Cache-Control: no-store, no-cache, must-revalidate");
        header("Cache-Control: post-check=0, pre-check=0", false);
        header("Pragma: no-cache");
        $folder = input('folder');
        if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
            exit; // finish preflight CORS requests here
        }
        if (!empty($_REQUEST['debug'])) {
            $random = rand(0, intval($_REQUEST['debug']));
            if ($random === 0) {
                header("HTTP/1.0 500 Internal Server Error");
                exit;
            }
        }
        // Settings
        $targetDir = $tmp_dir . DIRECTORY_SEPARATOR . 'file_material_tmp';            //存放分片临时目录
        if ($folder) {
            $uploadDir = $tmp_dir . DIRECTORY_SEPARATOR . 'file_material' . DIRECTORY_SEPARATOR . $folder . DIRECTORY_SEPARATOR . date('Ymd');
        } else {
            $uploadDir = $tmp_dir . DIRECTORY_SEPARATOR . 'file_material' . DIRECTORY_SEPARATOR . date('Ymd');    //分片合并存放目录
        }

        $cleanupTargetDir = true; // Remove old files
        $maxFileAge = 5 * 3600; // Temp file age in seconds

        // Create target dir
        if (!file_exists($targetDir)) {
            mkdir($targetDir, 0777, true);
        }
        // Create target dir
        if (!file_exists($uploadDir)) {
            mkdir($uploadDir, 0777, true);
        }
        // Get a file name
        if (isset($_REQUEST["name"])) {
            $fileName = $_REQUEST["name"];
        } elseif (!empty($_FILES)) {
            $fileName = $_FILES["file"]["name"];
        } else {
            $fileName = uniqid("file_");
        }
        $oldName = $fileName;

        $fileName = iconv('UTF-8', 'gb2312', $fileName);
        $filePath = $targetDir . DIRECTORY_SEPARATOR . $fileName;
        // $uploadPath = $uploadDir . DIRECTORY_SEPARATOR . $fileName;
        // Chunking might be enabled
        $chunk = isset($_REQUEST["chunk"]) ? intval($_REQUEST["chunk"]) : 0;
        $chunks = isset($_REQUEST["chunks"]) ? intval($_REQUEST["chunks"]) : 1;
        // Remove old temp files
        if ($cleanupTargetDir) {
            if (!is_dir($targetDir) || !$dir = opendir($targetDir)) {
                die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "Failed to open temp directory111."}, "id" : "id"}');
            }
            while (($file = readdir($dir)) !== false) {
                $tmpfilePath = $targetDir . DIRECTORY_SEPARATOR . $file;
                // If temp file is current file proceed to the next
                if ($tmpfilePath == "{$filePath}_{$chunk}.part" || $tmpfilePath == "{$filePath}_{$chunk}.parttmp") {
                    continue;
                }
                // Remove temp file if it is older than the max age and is not the current file
                if (preg_match('/\.(part|parttmp)$/', $file) && (filemtime($tmpfilePath) < time() - $maxFileAge)) {
                    unlink($tmpfilePath);
                }
            }
            closedir($dir);
        }
        // Open temp file
        if (!$out = fopen("{$filePath}_{$chunk}.parttmp", "wb")) {
            die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream222."}, "id" : "id"}');
        }
        if (!empty($_FILES)) {
            if ($_FILES["file"]["error"] || !is_uploaded_file($_FILES["file"]["tmp_name"])) {
                die('{"jsonrpc" : "2.0", "error" : {"code": 103, "message": "Failed to move uploaded file333."}, "id" : "id"}');
            }
            // Read binary input stream and append it to temp file
            if (!$in = fopen($_FILES["file"]["tmp_name"], "rb")) {
                die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream444."}, "id" : "id"}');
            }
        } else {
            if (!$in = fopen("php://input", "rb")) {
                die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream555."}, "id" : "id"}');
            }
        }
        while ($buff = fread($in, 4096)) {
            fwrite($out, $buff);
        }
        fclose($out);
        fclose($in);
        rename("{$filePath}_{$chunk}.parttmp", "{$filePath}_{$chunk}.part");
        $done = true;
        for ($index = 0; $index < $chunks; $index++) {
            if (!file_exists("{$filePath}_{$index}.part")) {
                $done = false;
                break;
            }
        }
        if ($done) {
            $pathInfo = pathinfo($fileName);
            $hashStr = substr(md5($pathInfo['basename']), 8, 16);
            $hashName = (int)(microtime(true) * 1000) . $hashStr . '.' . $pathInfo['extension'];
            $uploadPath = $uploadDir . DIRECTORY_SEPARATOR . $hashName;
            if (!$out = fopen($uploadPath, "wb")) {
                die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream666."}, "id" : "id"}');
            }
            //flock($hander,LOCK_EX)文件锁
            if (flock($out, LOCK_EX)) {
                for ($index = 0; $index < $chunks; $index++) {
                    if (!$in = fopen("{$filePath}_{$index}.part", "rb")) {
                        break;
                    }
                    while ($buff = fread($in, 4096)) {
                        fwrite($out, $buff);
                    }
                    fclose($in);
                    unlink("{$filePath}_{$index}.part");
                }
                flock($out, LOCK_UN);
            }
            fclose($out);

            $response = [
                'code' => 200,
                'success' => true,
                'oldName' => $oldName,
                'filePath' => $uploadPath,
//                'fileSize'=>$data['size'],
                'fileSuffixes' => $pathInfo['extension'],          //文件后缀名
//                'file_id'=>$data['id'],
            ];
            return json_encode($response);
        }
    }

    //新建文件夹
    public function AddFileType(Request $request)
    {
        if ($request->isAjax()) {
            $file_type = new FileType();
            $params = $request->param();
            $params['admin_id'] = $this->auth->id;
            if ($params) {
                $file_type->save($params);
                return json(['code' => 200, 'url' => '', 'msg' => '添加成功！']);
            }
        }
        return View::fetch('file_folder');
    }

    //下拉菜单
    public function select()
    {
        $res = FileType::where('admin_id', 'in', $this->childrenAdminIds)->field('id,id as value,name,pid as parent_id,status')->where('status', 1)->select();
        $result = toChildren($res, 'list');
        $data = [
            'code' => 0,
            'msg' => "获取成功",
            'trees' => $result
        ];
        return json($data);
    }

    //树图
    public function selectTree()
    {

        $res = FileType::where('admin_id', 'in', $this->childrenAdminIds)->field('id,name as title,pid as parent_id,status')->select();
        foreach ($res as $key => $v) {
            if ($v['status'] != 1) {
                $v['disabled'] = true;
            }
            $v['spread'] = true;
        }
        $result = toChildren($res, 'children');
        $data = [
            'code' => 0,
            'msg' => "获取成功",
            'data' => $result
        ];
        return json($data);
    }

    //更新树
    public function updateTree(Request $request)
    {
        $params = $request->param();
        if ($params) {
            FileType::update($params);
            return json(['code' => 200, 'url' => '', 'msg' => '更新成功！']);
        }
        return json(['code' => 400, 'url' => '', 'msg' => '错误信息！']);
    }

    //删除树
    public function delTree(Request $request)
    {

        $id = $request->param('id');
        $data = FileType::where('status', 1)->select();
        $ids = getChildsId($data, $id);
        array_push($ids, $id);
        $count = FileType::destroy($ids);
        if ($count) {
            return json(['code' => 200, 'url' => '', 'msg' => '删除成功！']);
        }
    }

    //更改树的状态
    public function updateStatus(Request $request)
    {
        if ($request->isAjax()) {
            $params = $request->param();
            if ($params) {
                FileType::update($params);
                return json(['code' => 200, 'url' => '', 'msg' => '更新成功！']);
            }
            return json(['code' => 400, 'url' => '', 'msg' => '错误信息！']);
        }
        return View::fetch();
    }

    //重命名
    public function Rename(Request $request)
    {
        if ($request->isAjax()) {
            $params = $request->param();
            if ($params) {
                \app\admin\model\File::update($params);
                return json(['code' => 200, 'url' => '', 'msg' => '变更成功！']);
            }
            return json(['code' => 400, 'url' => '', 'msg' => '错误信息！']);
        }
        return View::fetch();
    }


    //文件移动
    public function Shift(Request $request, $id)
    {
        $model = \app\admin\model\File::find($id);
        if ($request->isAjax()) {
            $params = $request->param();
            if ($params) {
                \app\admin\model\File::update($params);
                return json(['code' => 200, 'url' => '', 'msg' => '移动成功！']);
            }
            return json(['code' => 400, 'url' => '', 'msg' => '错误信息！']);
        }
        View::assign('id', $id);
        View::assign('model', $model);
        return View::fetch();
    }

    //删除文件
    public function del(Request $request)
    {
        $ids = ($request->param('source'));
        if ($ids) {
            $ids = explode(',', $ids);
            $count = \app\admin\model\File::destroy(array_values($ids));
            if ($count) {
                return json(['code' => 200, 'url' => '', 'msg' => '删除成功！']);
            }
        }

    }

    //文件下载
    public function FileDownload($id)
    {
//        $id = $request->param('source');

        $model = \app\admin\model\File::find($id);
        $true = Str::contains($model['name'],$model['suffix']);
        if ($true) {
            $new_name = $model['name'];
        } else {
            $new_name = $model['name'] . '.' . $model['suffix'];
        }



        $file = str_replace('\\', '/', $model['path']);
        $new_file = 'storage/' . $file;
        if (file_exists($new_file)) {
            downloadFile($new_file, $new_name);
        } else {
            echo "<script>alert('文件不存在')</script>";
        }
    }

}